<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" >

<title>Redis的RDB和AOF | 跬步</title>
<meta name="description" content="不积跬步，无以至千里">

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="shortcut icon" href="https://skylaugh.gitee.io/blog/favicon.ico?v=1698591240151">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0/katex.min.css">
<link rel="stylesheet" href="https://skylaugh.gitee.io/blog/styles/main.css">



<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>

<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />



  </head>
  <body>
    <div id="app" class="main">

      <div class="sidebar" :class="{ 'full-height': menuVisible }">
  <div class="top-container" data-aos="fade-right">
    <div class="top-header-container">
      <a class="site-title-container" href="https://skylaugh.gitee.io/blog">
        <img src="https://skylaugh.gitee.io/blog/images/avatar.png?v=1698591240151" class="site-logo">
        <h1 class="site-title">跬步</h1>
      </a>
      <div class="menu-btn" @click="menuVisible = !menuVisible">
        <div class="line"></div>
      </div>
    </div>
    <div>
      
        
          <a href="/blog/archives" class="site-nav">
            归档
          </a>
        
      
        
          <a href="/blog/tags" class="site-nav">
            标签
          </a>
        
      
        
          <a href="/blog/post/about" class="site-nav">
            关于
          </a>
        
      
    </div>
  </div>
  <div class="bottom-container" data-aos="flip-up" data-aos-offset="0">
    <div class="social-container">
      
        
      
        
      
        
      
        
      
        
      
    </div>
    <div class="site-description">
      不积跬步，无以至千里
    </div>
    <div class="site-footer">
      <a href="mailto:skylaugh@foxmail.com">Email</a> | <a class="rss" href="https://skylaugh.gitee.io/blog/atom.xml" target="_blank">RSS</a>
    </div>
  </div>
</div>


      <div class="main-container">
        <div class="content-container" data-aos="fade-up">
          <div class="post-detail">
            <h2 class="post-title">Redis的RDB和AOF</h2>
            <div class="post-date">2019-10-23</div>
            
              <div class="feature-container" style="background-image: url('https://skylaugh.gitee.io/blog/post-images/redis-de-rdb-he-aof.jpg')">
              </div>
            
            <div class="post-content">
              <p>从一道面试题开始说起吧</p>
<blockquote>
<h3 id="redis-1s-set-10w次有什么问题及问题产生的原因">Redis 1s set 10w次有什么问题，及问题产生的原因。</h3>
</blockquote>
<ol>
<li>写请求太多阻塞其他请求，导致性能下降</li>
<li>触发 rdb 备份操作，fork 新线程也会阻塞其他操作，</li>
<li>在 rdb 备份时，如果 set 请求的太多，可能会导致内存暴涨一倍，导致内存不足，或者使用 swap 导致性能下降。</li>
<li>如果开启了 AOF 备份方式，可能会导致频繁刷新缓冲区数据到磁盘，导致性能下降。进一步阻塞请求。</li>
</ol>
<h3 id="redis-的-rdb-是什么">Redis 的 RDB 是什么？</h3>
<ol>
<li>在指定的时间间隔内将内存中的数据集快照写入磁盘，也就是Snapshot快照，恢复时是将快照文件直接读到内存里。</li>
<li>持久化时Redis会单独创建(fork)一个子进程来进行持久化，子进程先将数据写入到一个临时文件中，待持久化过程都结束了，再用这个临时文件替换上次持久化好的文件。</li>
<li>整个过程中主进程不进行任何IO操作，这就确保了极高的性能。</li>
<li>进行大规模数据的恢复，且对于恢复的完整性不是非常敏感，那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。</li>
</ol>
<h3 id="rdb-的优缺点">RDB 的优缺点</h3>
<p>优点：</p>
<ol>
<li>适合大规模的数据恢复。</li>
<li>如果业务对数据完整性和一致性要求不高，RDB是很好的选择。</li>
</ol>
<p>缺点：</p>
<ol>
<li>数据的完整性和一致性不高，因为RDB可能在最后一次备份时宕机了。</li>
<li>备份时占用内存，因为Redis 在备份时会独立创建一个子进程，将数据写入到一个临时文件（此时内存中的数据是原来的两倍哦），最后再将临时文件替换之前的备份文件。<br>
所以Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。</li>
</ol>
<h3 id="fork线程">fork线程</h3>
<ul>
<li>fork的作用是复制一个与当前进程一样的进程。新进程的所有数据（变量、环境变量、程序计数器等）数值都和原进程一致，但是是一个全新的进程，并作为原进程的子进程</li>
</ul>
<h3 id="aof">AOF</h3>
<p>Redis 默认不开启。它的出现是为了弥补RDB的不足（数据的不一致性），所以它采用日志的形式来记录每个<strong>写操作</strong>，并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。</p>
<h3 id="从配置文件了解aof">从配置文件了解AOF</h3>
<p>打开 <code>redis.conf</code> 文件，找到 <code>APPEND ONLY MODE</code> 对应内容</p>
<ol>
<li>redis 默认关闭，开启需要手动把no改为yes</li>
</ol>
<pre><code>appendonly yes
</code></pre>
<ol start="2">
<li>指定本地数据库文件名，默认值为 <code>appendonly.aof</code></li>
</ol>
<pre><code>appendfilename &quot;appendonly.aof&quot;
</code></pre>
<ol start="3">
<li>指定更新日志条件</li>
</ol>
<pre><code># appendfsync always
appendfsync everysec
# appendfsync no
</code></pre>
<p>解说：</p>
<ul>
<li>always：同步持久化，每次发生数据变化会立刻写入到磁盘中。性能较差当数据完整性比较好（慢，安全）</li>
<li>everysec：出厂默认推荐，每秒异步记录一次（默认值）</li>
<li>no：不同步</li>
</ul>
<ol start="4">
<li>配置重写触发机制</li>
</ol>
<pre><code>auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
</code></pre>
<p>解说：当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。一般都设置为3G，64M太小了。</p>
<h4 id="触发aof快照">触发AOF快照</h4>
<p>根据配置文件触发，可以是每次执行触发，可以是每秒触发，可以不同步。</p>
<h4 id="根据aof文件恢复数据">根据AOF文件恢复数据</h4>
<p>正常情况下，将appendonly.aof 文件拷贝到redis的安装目录的bin目录下，重启redis服务即可。但在实际开发中，可能因为某些原因导致appendonly.aof 文件格式异常，从而导致数据还原失败，可以通过命令<code>redis-check-aof --fix appendonly.aof</code> 进行修复 。</p>
<h4 id="aof的重写机制">AOF的重写机制</h4>
<p>前面也说到了，AOF的工作原理是将写操作追加到文件中，文件的冗余内容会越来越多。所以聪明的 Redis 新增了重写机制。当AOF文件的大小超过所设定的阈值时，Redis就会对AOF文件的内容压缩。</p>
<h4 id="重写的原理">重写的原理</h4>
<p>Redis 会 fork 出一条新进程，读取内存中的数据，并重新写到一个临时文件中（并没有读取旧文件）。最后替换旧的aof文件。</p>
<p>触发机制：当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。这里的“一倍”和“64M” 可以通过配置文件修改。</p>
<h3 id="aof-的优缺点">AOF 的优缺点</h3>
<p>优点：数据的完整性和一致性更高<br>
缺点：因为AOF记录的内容多，文件会越来越大，数据恢复也会越来越慢。</p>
<h2 id="总结">总结：</h2>
<ol>
<li>Redis 默认开启RDB持久化方式，在指定的时间间隔内，执行指定次数的写操作，则将内存中的数据写入到磁盘中。</li>
<li>RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。</li>
<li>Redis 需要手动开启AOF持久化方式，默认是每秒将写操作日志追加到AOF文件中。</li>
<li>AOF 的数据完整性比RDB高，但记录内容多了，会影响数据恢复的效率。</li>
<li>Redis 针对 AOF文件大的问题，提供重写的瘦身机制。</li>
<li>若只打算用Redis 做缓存，可以关闭持久化。</li>
<li>若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份，留一后手。AOF出问题了，还有RDB。</li>
</ol>

            </div>
            
              <div class="tag-container">
                
                  <a href="https://skylaugh.gitee.io/blog/tag/k7pFygIgX/" class="tag">
                    缓存
                  </a>
                
              </div>
            
            
              <div class="next-post">
                <div class="next">下一篇</div>
                <a href="https://skylaugh.gitee.io/blog/post/hong-hei-shu/">
                  <h3 class="post-title">
                    红黑树
                  </h3>
                </a>
              </div>
            

            

          </div>

        </div>
      </div>
    </div>

    <script src="https://unpkg.com/aos@next/dist/aos.js"></script>

<script type="application/javascript">

AOS.init();

hljs.initHighlightingOnLoad()

var app = new Vue({
  el: '#app',
  data: {
    menuVisible: false,
  },
})

</script>




  </body>
</html>
